<template>
  <div ref="imgWrapRef" class="cropper-container w-full mx-auto md:w-2/3 xl:w-2/5 relative bg-gray-900">
    <img class="w-full" ref="imageRef" />
    <div class="w-28 h-28 overflow-hidden absolute top-0 right-0" ref="prevRef"></div>
  </div>
  <div class="fixed bottom-0 left-0 flex-col gap-x-4 flex justify-end w-full box-border pb-2 px-4 z-[1001]">
    <div
      class="absolute bottom-[16px] transition-all bg-black/50 w-[68px] h-[438px] flex justify-center"
      :style="{ right: speedOffset }"
    >
      <v-slider v-model="step" :min="0.01" :max="0.3" color="orange" direction="vertical">
        <template v-slot:prepend>
          <div class="orange-500 text-white text-sm">速度</div>
        </template>
        <template v-slot:append>
          <div class="orange-500 text-white text-sm">{{ sped }}</div>
        </template>
      </v-slider>

      <div
        class="absolute -left-[32px] w-[32px] top-[20px] flex flex-col justify-center justify-items-center items-center gap-y-4 bg-black/80 py-4"
      >
        <div @click="speedSliderIsShow = !speedSliderIsShow" class="w-[20px] h-[20px]">
          <j-icon size="20" color="#ffffff">速度</j-icon>
        </div>

        <div @click="move(-1)" class="w-[20px] h-[20px] rotate-[90deg]">
          <j-icon size="20" color="#ffffff">MdiSkipPreviousCircle</j-icon>
        </div>

        <div @click="slowMove()" class="w-[20px] h-[20px]">
          <j-icon size="20" color="#ffffff">{{ animationId == null ? "MdiPlayCircle" : "MdiPauseCircle" }}</j-icon>
        </div>

        <div @click="move(1)" class="w-[20px] h-[20px] rotate-[90deg]">
          <j-icon size="20" color="#ffffff">MdiSkipNextCircle</j-icon>
        </div>

     

        <v-dialog max-width="500">
          <template v-slot:activator="{ props: activatorProps }">
            <div v-bind="activatorProps" class="w-[20px] h-[20px]">
              <j-icon size="20" color="#ffffff">目录</j-icon>
            </div>
          </template>
          <template v-slot:default="{ isActive }">
            <v-card>
              <div class="flex flex-col p-4 rounded-lg" style="border: 1px solid #dbdbdb">
                <QuickOptions v-model="modelValue" @change="() => emit('change')" />
              </div>
            </v-card>
          </template>
        </v-dialog>

        <div @click="handleCreateCanvas()" class="w-[20px] h-[20px]">
          <j-icon size="20" color="#ffffff">调色盘</j-icon>
        </div>

        <div @click="onSclaceAsyncDropPositionAndSize()" class="w-[20px] h-[20px] rotate-[90deg]">
          <j-icon size="20" color="#ffffff">两端对齐</j-icon>
        </div>
      </div>
    </div>

    <div class="fixed flex gap-x-4 transition-all" :style="{ top: editing ? '0px' : '-60px' }">
      <v-chip-group v-model="currentShapeType" selected-class="text-white">
        <v-chip class="bg-orange" v-for="(item, index) in shapesType" :value="item.value" :key="index">{{
          item.text
        }}</v-chip>
      </v-chip-group>
    </div>
    <div class="flex gap-x-4 mb-0 flex-wrap gap-2"></div>
  </div>
</template>

<script setup name="JcGePuTouYing">
import { computed, onMounted, onUnmounted, ref, watch, useModel } from "vue";
import useController from "../../hooks/useController";
import "cropperjs/dist/cropper.css";
import Cropper from "cropperjs";
import useCurrentSgData from "../../hooks/useCurrentSgData";
import { useTransition, TransitionPresets, executeTransition } from "@vueuse/core";
import { shallowRef } from "vue";
import { SheapTypeEnum } from "./enum";
import QuickOptions from "../Config/QuickOptions.vue";
// #App结构 - 图形编辑器 [editor]

import "@leafer-in/editor"; // 导入图形编辑器插件
import "@leafer-in/viewport"; // 导入视口插件(可选)
import useLeaferCanvas from "./useLeaferCanvas";
const shapesType = Object.keys(SheapTypeEnum).map((key) => SheapTypeEnum[key]);
const currentShapeType = ref("none");
const speedSliderIsShow = ref(false);
const speedOffset = computed(() => (speedSliderIsShow.value ? "0px" : "-66px"));

const drawingBoardIsShow = ref(false);
const drawingBoardOffset = computed(() => (drawingBoardIsShow.value ? "0px" : "-68px"));

const imgWrapRef = ref(null);
const corpTop = shallowRef(0);
const outCorpTop = useTransition(corpTop, {
  duration: 400,
  transition: TransitionPresets.linear,
});
const props = defineProps({
  modelValue: { type: Object, default: () => ({}) },
});

const emit = defineEmits(["update:modelValue", "change"]);
const modelValue = useModel(props, "modelValue", emit);
const { gepuUrl } = useController(modelValue, emit);
const currentData = useCurrentSgData(modelValue);
const imageRef = ref(null);
const prevRef = ref(null);
let cropper;
const loading = ref(false);
const maxHeight = window.innerHeight - 122;
const maxWidth = window.innerWidth;
const { createCanvas, clear, editing } = useLeaferCanvas(currentShapeType, (base64) => {
  if (editing.value) {
    modelValue.value.gepuOptions.HBbase64 = base64;
    emit("change");
  }
});
onMounted(() => {
  init();
});

onUnmounted(() => {
  cropper?.destroy();
});

function init() {
  if (!gepuUrl.value) return;
  const image = imageRef.value;
  if (cropper) {
    image.removeEventListener("crop", onChange);
    image.removeEventListener("ready", onReady);
    cropper?.destroy();
    cropper = null;
  }
  image.src = gepuUrl.value;
  image.alt = "Picture";
  cropper = new Cropper(image, {
    viewMode: 0,
    autoCropArea: 0.2 / 1,
    dragMode: "move",
    preview: prevRef.value, 
     
  });
  image.addEventListener("ready", onReady);
  image.addEventListener("crop", onChange);
}
function onReady(event) {
  setTimeout(() => {
    cropper.setCropBoxData({
      left: 0,
      top: 0,
      width: maxWidth,
      height: maxWidth * (9 / 16),
    });
  }, 500);
}

function onChange(event) {
  cancelAimFrame();
  const imgData = cropper.getImageData();
  const data = event.detail;
  modelValue.value.gepuOptions = { imgData, data };



     emit("change");
}

function move(dir = -1) {
  if (cropper) {
    cancelAimFrame();
    const { top, height } = cropper.getCropBoxData();
    const nextTop = top + height * dir;
    corpTop.value = nextTop;
  }
}

let animationId = ref(null);
const step = ref(0.05);
const sped = computed(() => {
  return Math.round(step.value * 100);
});

// 缓慢下移
function slowMove() {
  if (cropper) {
    if (animationId.value != null) {
      cancelAimFrame();
      return;
    }
    const { top, height: cropBoxHeight } = cropper.getCropBoxData();
    const { height } = cropper.getContainerData();
    let form = top;
    const to = height - cropBoxHeight;
    function move() {
      form += step.value;
      if (form > to) {
        cancelAimFrame();
        return;
      }
      cropper.setCropBoxData({
        top: form,
      });
    }

    function animate() {
      if (animationId.value != null) return;
      animationId.value = requestAnimationFrame(() => {
        move();
        animate();
      });
    }

    animate();
  }
}

function cancelAimFrame() {
  cancelAnimationFrame(animationId.value);
  animationId.value = null;
  
}

function handleCreateCanvas() {
  if (editing.value) {
    clear();
    changeHBbase64("");
    return;
  }
  cancelAimFrame();
  createCanvas(cropper, imgWrapRef);
}

function changeHBbase64(base64) {
  modelValue.value.gepuOptions.HBbase64 = base64;
  emit("change");
}

function onSclaceAsyncDropPositionAndSize(){
  const {width, top,left} = cropper.getCanvasData();
  const {height:cropHeight,width:cropWidth} = cropper.getCropBoxData();
  cropper.setCropBoxData({
    top: top,
    left: left,
    width: width, 
    height: cropHeight * (width / cropWidth),
  })
}

watch(outCorpTop, () => {
  cropper.setCropBoxData({
    top: outCorpTop.value,
  });
});

watch(gepuUrl, () => {
  init();
});
</script>
<style lang="scss" scoped>
:deep(.cropper-point) {
  width: 28px;
  height: 28px;
}
</style>
